/**
 * 
 */
package GUI.network;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.StreamCorruptedException;
import java.net.Socket;
import java.net.UnknownHostException;

import officeserver.office.request.AdminRequest;
import officeserver.office.request.UserRequest;
import officeserver.office.request.AdminRequest.TYPE;
import officeserver.office.request.OfficeRequest;

/**
 * @author Chris Bayruns
 * 
 */
public class NetworkConnection {
	public class MYObjectInputStream extends ObjectInputStream{

		public MYObjectInputStream(InputStream in) throws IOException
		{
			super(in);
			// TODO Auto-generated constructor stub
		}
		@Override 
		protected Class resolveClass(ObjectStreamClass desc) throws IOException,ClassNotFoundException
               {
				OfficeRequest bla = new UserRequest(null, null);
				return ((Object)bla).getClass();
			
               }
		
	}
    private String host;
    private int port;
    private Socket mySocket;
    private DataOutputStream outStream;
    //private ObjectInputStream inStream;
    private DataInputStream din;
    private BufferedInputStream myBufIn = null;
    public final int timeout = 20; // seconds

    /**
     * @author Chris Bayruns
     * @param host
     *            The host to connect to.
     * @param port
     *            The port to connect to.
     * @throws IOException
     * @throws UnknownHostException
     */
    public NetworkConnection(String host, int port)
	    throws UnknownHostException, IOException {
	this.host = host;
	this.port = port;
	connect();
    }

    public void connect() throws UnknownHostException, IOException {
	mySocket = new Socket(host, port);
	outStream = new DataOutputStream(mySocket.getOutputStream());
	// outStream.flush();
	//myBufIn = new BufferedInputStream(mySocket.getInputStream());
	//inStream = new MYObjectInputStream(mySocket.getInputStream());
	
	din = new DataInputStream(mySocket.getInputStream());
    }

    public void disconnect() throws IOException {
	if (mySocket != null) {

	    //outStream.writeObject(new AdminRequest(TYPE.CON_DISCONNECT));
	    outStream.flush();
	    outStream.flush();
	    //outStream.reset();
	    outStream.close();
	    //inStream.reset();
	    //inStream.close();
	    myBufIn.close();
	    mySocket.close();
	    // mySocket.
	}
    }

    /**
     * @author Chris Bayruns
     * @return If the net is connected.
     */
    public boolean isConnected() {
	if (mySocket != null) {
	    return mySocket.isConnected();
	} else {
	    return false;
	}
    }

    /**
     * @return the host
     */
    public String getHost() {
	return host;
    }

    /**
     * @param host
     *            the host to set
     */
    public void setHost(String host) {
	this.host = host;
    }

    /**
     * @return the port
     */
    public int getPort() {
	return port;
    }

    /**
     * @param port
     *            the port to set
     */
    public void setPort(int port) {
	this.port = port;
    }

    public OfficeRequest request(OfficeRequest in) {
	OfficeRequest result = null;
	//Object tempIn  =null;
	long time;
	byte [] tempA;
	int num;
	try{
	if (mySocket.isConnected()) {
		tempA = toBytes(in);
		//System.out.println( "writing out: " + tempA.length + " for" + in.toString() );
		outStream.writeInt(tempA.length);
		//outStream.
	    outStream.write(tempA);
	    outStream.flush();
	    time = System.currentTimeMillis();
	    Thread.sleep(200);
	    	//System.out.print( "Avaliable: " + din.available());
		    if( din.available() > 0 )
		    {
				num = din.readInt();
				//System.out.print( "reading in: " + num + "::::::::::or ");
				tempA = new byte[num];
				try{
					/*for( int i = 0; i < num; i++ )
					{
						tempA[i] = din.readByte();
					}*/
					din.readFully(tempA);
					
					}catch(java.io.EOFException e)
					{
						
					}
				
		    	/*tempA = new byte[myBufIn.available()];
		    	myBufIn.read(tempA);*/
			    //Object temp = inStream.readObject();
			    Object temp = bytesToObject(tempA);
			    if( temp instanceof OfficeRequest)
			    	result = (OfficeRequest)temp;
		    }
		    //System.out.println( result );
			//outStream.reset();
	}
	}
	catch( Exception e )
	{
		
	}
	return result;
    }
    
    private OfficeRequest bytesToObject( byte bytes[] ) throws IOException, ClassNotFoundException
    {
    	OfficeRequest result = null;
    	
		result = (OfficeRequest) new java.io.ObjectInputStream(new
		java.io.ByteArrayInputStream(bytes)).readObject();

		return result;
    }
    
    private static byte[] toBytes(Object object)
    {
		java.io.ByteArrayOutputStream baos = new
		java.io.ByteArrayOutputStream();
		try{
			java.io.ObjectOutputStream oos = new
			java.io.ObjectOutputStream(baos);
			oos.writeObject(object);
		}catch(java.io.IOException ioe){
			ioe.printStackTrace();
		}
		
		return baos.toByteArray();
	} 
    
}
